This repository was archived by the owner on Jul 24, 2026. It is now read-only.
fix(up): a fresh foreground convoy up UN-PARKS its members — restore the FULL fleet after an outage - #106
Merged
Merged
Conversation
…e the FULL fleet after an outage Parking-recovery for the 2026-07-22 incident: a supervisor bring-up after a mass outage brought back only part of the fleet; the rest stayed PARKED from a prior supervisor's give-up and had to be hand-launched. Root cause: `strategy.status=flapping` + the fast-fail counter PERSIST to a session's tags (the on-disk supervision contract), so they outlive the supervisor that wrote them. An outage drives the cap to its limit → the agents park → and a fresh `convoy up`, reading those stale tags, hits classify's `isFlapping → skip` and never relaunches them. Fix: a foreground `convoy up` is a DELIBERATE bring-up — the operator gesture that says "restore the fleet" — so at startup it clears the park AND zeroes the fast-fail counter for permanent members (regardless of prior fail count), giving each a fresh cap budget. The cap still re-accrues tick-to-tick WITHIN this supervisor's watch (the real crash-loop protection). The `--once` shepherd cron does NOT un-park: it runs every few minutes, so un-parking there would relaunch a genuinely broken agent every tick — parking must stay durable for it. - flapping-cap.ts: `clearParkForFreshSupervisor` (pure) — the reset decision, unit-tested. - up.ts: the FRESH-SUPERVISOR UN-PARK startup pass (foreground only), which clears the on-disk park (removes the status tag — updateTags MERGES) and seeds the in-memory classifier state. - Tests: pure cases for the reset + a process-level proof (a parked, gone-but-recorded agent is UN-PARKED and RELAUNCHED by a fresh foreground up, while `--once` leaves it parked). Part 2 of 4 of the decoupling-hardening task. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014gbfntB6cu21sL4YBp21LF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Parking-recovery for the 2026-07-22 incident: a supervisor bring-up after a mass outage brought back only part of the fleet — the rest stayed parked from a prior supervisor's give-up and had to be hand-launched.
Root cause
strategy.status=flappingand the fast-fail counter persist to a session's tags (the on-disk supervision contract), so they outlive the supervisor that wrote them. An outage drives the cap to its limit → the agents park → and a freshconvoy up, reading those stale tags, hits classify'sisFlapping → skipand never relaunches them.Fix
A foreground
convoy upis a deliberate bring-up — the operator gesture that says "restore the fleet" — so at startup it clears the park AND zeroes the fast-fail counter for permanent members (regardless of prior fail count), giving each a fresh cap budget. The cap still re-accrues tick-to-tick within this supervisor's watch (the real crash-loop protection).The
--onceshepherd cron does NOT un-park: it runs every few minutes, so un-parking there would relaunch a genuinely broken agent every tick — parking must stay durable for it.Changes
flapping-cap.ts:clearParkForFreshSupervisor(pure) — the reset decision, unit-tested.up.ts: the FRESH-SUPERVISOR UN-PARK startup pass (foreground only) — clears the on-disk park (removes the status tag, sinceupdateTagsmerges) and seeds the in-memory classifier state so the first tick relaunches.--onceleaves it parked.Full suite green (546 tests).
Part 2 of 4 of the decoupling-hardening task (decisive test #105 → parking fix →
convoy restart→ self-sever guard).Note / possible follow-up
The un-park pass keys on
isPermanent(s)(thestrategy=permanentpty tag). A gone session that has lost that tag (e.g. stripped by apty kill) would be treated as a worker and skipped by both this pass and the session loop, while the catalog pass defers to the session loop — a distinct "catalog says permanent, pty tag missing" gap. Flagging it separately rather than widening this PR's scope; happy to take it as a follow-up if it's worth closing.🤖 Generated with Claude Code
https://claude.ai/code/session_014gbfntB6cu21sL4YBp21LF